﻿using QYmall.Core.Common.Emum;
using QYmall.Core.Common.Helper;
using QYmall.Core.Common.Extensions;
using QYmall.Core.Model.Models;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;

namespace QYmall.Core.DBFactory.Database
{
    public class AppDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, int,
        ApplicationUserClaim, ApplicationUserRole, ApplicationUserLogin, ApplicationRoleClaim, ApplicationUserToken>
    {
        private readonly DBType _dbType;
        private readonly string _connectionString = string.Empty;
        /// <summary>
        /// 默认连接写数据库
        /// </summary>
        public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) {
            _dbType = Appsettings.GetValue(new string[] { "ConnectionStrings", "DBType" }).ToEnum<DBType>();//数据库类型
            _connectionString = Appsettings.GetValue(new string[] { "ConnectionStrings", "WriteConnection" });//连接字符串
        }
        /// <summary>
        /// 指定读写分离模式连接
        /// </summary>
        public AppDbContext(DBType? dbType, string? connectionString)
        {
            _dbType = dbType ?? DBType.SqlServer; //数据库类型
            _connectionString = connectionString ?? String.Empty; //连接字符串
        }

        #region 实体到表的映射===========================
        //系统
        public DbSet<Advert>? dt_app_advert { get; private set; }
        public DbSet<AdvertBanner>? dt_app_advert_banner { get; private set; }
        public DbSet<Areas>? dt_areas { get; private set; }
        public DbSet<Manager>? dt_manager { get; private set; }
        public DbSet<ManagerLog>? dt_manager_log { get; private set; }
        public DbSet<ManagerMenu>? dt_manager_menu { get; private set; }
        public DbSet<MerchantMenu>? dt_merchant_menu { get; private set; }
        public DbSet<NotifyTemplate>? dt_notify_template { get; private set; }
        public DbSet<OAuths>? dt_oauths { get; private set; }
        public DbSet<OAuthLogin>? dt_oauth_login { get; private set; }
        public DbSet<Payment>? dt_payment { get; private set; }
        public DbSet<SysConfig>? dt_sysconfig { get; private set; }

        //文章
        public DbSet<Articles>? dt_articles { get; private set; }
        public DbSet<ArticleCategory>? dt_article_category { get; private set; }
        public DbSet<ArticleCategoryRelation>? dt_article_category_relation { get; private set; }

        //会员
        public DbSet<Members>? dt_members { get; private set; }
        public DbSet<MemberGroup>? dt_member_group { get; private set; }
        public DbSet<MemberAddress>? dt_member_address { get; private set; }
        public DbSet<MemberMessage>? dt_member_message { get; private set; }
        public DbSet<MemberInvoice>? dt_member_invoice { get; private set; }
        public DbSet<MemberRecharge>? dt_member_recharge { get; private set; }
        public DbSet<MemberPointLog>? dt_member_point_log { get; private set; }
        public DbSet<MemberAmountLog>? dt_member_amount_log { get; private set; }

        //商户
        public DbSet<Merchants>? dt_merchants { get; private set; }
        public DbSet<MerchantStore>? dt_merchant_store { get; private set; }
        public DbSet<MerchantCategory>? dt_merchant_category { get; private set; }
        public DbSet<MerchantAmountLog>? dt_merchant_amount_log { get; private set; }
        public DbSet<MerchantCash>? dt_merchant_cash { get; private set; }
        public DbSet<MerchantPayinfo>? dt_merchant_payinfo { get; private set; }
        public DbSet<MerchantFavorite>? dt_merchant_favorite { get; private set; }
        public DbSet<MerchantArticle>? dt_merchant_article { get; private set; }
        public DbSet<MerchantArticleCategory>? dt_merchant_article_category { get; private set; }

        //商城
        public DbSet<ShopBrand>? dt_shop_brand { get; private set; }
        public DbSet<ShopCart>? dt_shop_cart { get; private set; }
        public DbSet<ShopCategory>? dt_shop_category { get; private set; }
        public DbSet<ShopCategoryGoodsRelation>? dt_shop_category_goods_relation { get; private set; }
        public DbSet<ShopCategorySku>? dt_shop_category_sku { get; private set; }
        public DbSet<ShopConvert>? dt_shop_convert { get; private set; }
        public DbSet<ShopConvertHistory>? dt_shop_convert_history { get; private set; }
        public DbSet<ShopCoupon>? dt_shop_coupon { get; private set; }
        public DbSet<ShopCouponGoodsRelation>? dt_shop_coupon_goods_relation { get; private set; }
        public DbSet<ShopCouponHistory>? dt_shop_coupon_history { get; private set; }
        public DbSet<ShopDelivery>? dt_shop_delivery { get; private set; }
        public DbSet<ShopDeliveryArea>? dt_shop_delivery_area { get; private set; }
        public DbSet<ShopExpress>? dt_shop_express { get; private set; }
        public DbSet<ShopField>? dt_shop_field { get; private set; }
        public DbSet<ShopFieldOption>? dt_shop_field_option { get; private set; }
        public DbSet<ShopGoods>? dt_shop_goods { get; private set; }
        public DbSet<ShopGoodsAlbum>? dt_shop_goods_album { get; private set; }
        public DbSet<ShopGoodsFavorite>? dt_shop_goods_favorite { get; private set; }
        public DbSet<ShopGoodsFieldValue>? dt_shop_goods_field_value { get; private set; }
        public DbSet<ShopGoodsGroupPrice>? dt_shop_goods_group_price { get; private set; }
        public DbSet<ShopGoodsProduct>? dt_shop_goods_product { get; private set; }
        public DbSet<ShopGoodsSku>? dt_shop_goods_sku { get; private set; }
        public DbSet<ShopLabel>? dt_shop_label { get; private set; }
        public DbSet<ShopLabelGoodsRelation>? dt_shop_label_goods_relation { get; private set; }
        public DbSet<ShopPresell>? dt_shop_presell { get; private set; }
        public DbSet<ShopPromotion>? dt_shop_promotion { get; private set; }
        public DbSet<ShopSkus>? dt_shop_skus { get; private set; }
        public DbSet<ShopSpeed>? dt_shop_speed { get; private set; }

        //订单
        public DbSet<Orders>? dt_orders { get; private set; }
        public DbSet<OrderGoods>? dt_order_goods { get; private set; }
        public DbSet<OrderLog>? dt_order_log { get; private set; }
        public DbSet<OrderDelivery>? dt_order_delivery { get; private set; }
        public DbSet<OrderDeliveryGoods>? dt_order_delivery_goods { get; private set; }
        public DbSet<OrderInvoice>? dt_order_invoice { get; private set; }
        public DbSet<OrderInvoiceGoods>? dt_order_invoice_goods { get; private set; }
        public DbSet<OrderEvaluate>? dt_order_evaluate { get; private set; }
        public DbSet<OrderEvaluateAlbum>? dt_order_evaluate_album { get; private set; }
        public DbSet<OrderRefund>? dt_order_refund { get; private set; }
        public DbSet<OrderRefundGoods>? dt_order_refund_goods { get; private set; }
        public DbSet<OrderRefundAlbum>? dt_order_refund_album { get; private set; }
        public DbSet<OrderCollection>? dt_order_collection { get; private set; }
        public DbSet<OrderCollectionRelation>? dt_order_collection_relation { get; private set; }
        public DbSet<OrderPromotion>? dt_order_promotion { get; private set; }
        #endregion

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            //默认只写了三种数据库，有需要自行加
            switch (_dbType)
            {
                case DBType.MySql:
                    optionsBuilder.UseMySql(_connectionString, ServerVersion.AutoDetect(_connectionString));
                    break;
                case DBType.Oracle:
                    optionsBuilder.UseOracle(_connectionString);
                    break;
                default:
                    optionsBuilder.UseSqlServer(_connectionString);
                    break;
            }
        }

        /// <summary>
        /// 模型构建器
        /// </summary>
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            //用户导航属性与外健关系
            modelBuilder.Entity<ApplicationUser>(b =>
            {
                b.HasMany(e => e.Claims).WithOne(e => e.User).HasForeignKey(uc => uc.UserId).IsRequired();
                b.HasMany(e => e.Logins).WithOne(e => e.User).HasForeignKey(ul => ul.UserId).IsRequired();
                b.HasMany(e => e.Tokens).WithOne(e => e.User).HasForeignKey(ut => ut.UserId).IsRequired();
                b.HasMany(e => e.UserRoles).WithOne(e => e.User).HasForeignKey(ur => ur.UserId).IsRequired();
            });
            modelBuilder.Entity<ApplicationRole>(b =>
            {
                b.HasMany(e => e.UserRoles).WithOne(e => e.Role).HasForeignKey(ur => ur.RoleId).IsRequired();
                b.HasMany(e => e.RoleClaims).WithOne(e => e.Role).HasForeignKey(rc => rc.RoleId).IsRequired();
            });
            //配置实体类型映射到的表名
            modelBuilder.Entity<ApplicationUser>().ToTable("dt_users");
            modelBuilder.Entity<ApplicationRole>().ToTable("dt_roles");
            modelBuilder.Entity<ApplicationUserLogin>().ToTable("dt_user_logins");
            modelBuilder.Entity<ApplicationUserClaim>().ToTable("dt_user_claims");
            modelBuilder.Entity<ApplicationUserRole>().ToTable("dt_user_roles");
            modelBuilder.Entity<ApplicationRoleClaim>().ToTable("dt_role_claims");
            modelBuilder.Entity<ApplicationUserToken>().ToTable("dt_user_tokens");

            //特殊外健关系处理，防止多重级联数据迁移失败
            modelBuilder.Entity<ShopCoupon>().HasOne(x => x.Merchant).WithMany().OnDelete(DeleteBehavior.Restrict);
            modelBuilder.Entity<ShopConvert>().HasOne(x => x.Merchant).WithMany().OnDelete(DeleteBehavior.Restrict);
            modelBuilder.Entity<ShopConvertHistory>().HasOne(x => x.Order).WithMany().OnDelete(DeleteBehavior.Restrict);
            modelBuilder.Entity<ShopSpeed>().HasOne(x => x.Merchant).WithMany().OnDelete(DeleteBehavior.Restrict);
            modelBuilder.Entity<ShopPresell>().HasOne(x => x.Merchant).WithMany().OnDelete(DeleteBehavior.Restrict);
            modelBuilder.Entity<ShopPromotion>().HasOne(x => x.Merchant).WithMany().OnDelete(DeleteBehavior.Restrict);
            modelBuilder.Entity<Orders>().HasOne(x => x.Merchant).WithMany().OnDelete(DeleteBehavior.Restrict);
            modelBuilder.Entity<OrderEvaluate>().HasOne(x => x.OrderGoods).WithMany().OnDelete(DeleteBehavior.Restrict);
            
            //批量删除外键关健防止多重级联，启用后无法自动删除关联表
            /*var foreignKeys = modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys()).Where(fk => fk.DeleteBehavior == DeleteBehavior.Cascade);
            foreach (var fk in foreignKeys)
            {
                fk.DeleteBehavior = DeleteBehavior.Restrict;
            }*/

            //添加种子数据
            IList<SysConfig>? configList = JsonHelper.ToJson<IList<SysConfig>>(File.ReadAllText(FileHelper.GetCurrPath(@"/DataSeed/dt_sysconfig.json")));
            if (configList != null)
            {
                modelBuilder.Entity<SysConfig>().HasData(configList);
            }
            IList<ApplicationRole>? roleList = JsonHelper.ToJson<IList<ApplicationRole>>(File.ReadAllText(FileHelper.GetCurrPath(@"/DataSeed/dt_roles.json")));
            if (roleList != null)
            {
                modelBuilder.Entity<ApplicationRole>().HasData(roleList);
            }
            IList<ApplicationUser>? userList = JsonHelper.ToJson<IList<ApplicationUser>>(File.ReadAllText(FileHelper.GetCurrPath(@"/DataSeed/dt_users.json")));
            if(userList != null)
            {
                modelBuilder.Entity<ApplicationUser>().HasData(userList);
            }
            IList<ApplicationUserRole>? userRoleList = JsonHelper.ToJson<IList<ApplicationUserRole>>(File.ReadAllText(FileHelper.GetCurrPath(@"/DataSeed/dt_user_roles.json")));
            if (userRoleList != null)
            {
                modelBuilder.Entity<ApplicationUserRole>().HasData(userRoleList);
            }
            IList<Manager>? managerList = JsonHelper.ToJson<IList<Manager>>(File.ReadAllText(FileHelper.GetCurrPath(@"/DataSeed/dt_manager.json")));
            if(managerList != null)
            {
                modelBuilder.Entity<Manager>().HasData(managerList);
            }
            IList<ManagerMenu>? managerMenu = JsonHelper.ToJson<IList<ManagerMenu>>(File.ReadAllText(FileHelper.GetCurrPath(@"/DataSeed/dt_manager_menu.json")));
            if (managerMenu != null)
            {
                modelBuilder.Entity<ManagerMenu>().HasData(managerMenu);
            }
            IList<MerchantMenu>? merchantMenu = JsonHelper.ToJson<IList<MerchantMenu>>(File.ReadAllText(FileHelper.GetCurrPath(@"/DataSeed/dt_merchant_menu.json")));
            if (merchantMenu != null)
            {
                modelBuilder.Entity<MerchantMenu>().HasData(merchantMenu);
            }
            IList<NotifyTemplate>? notifyList = JsonHelper.ToJson<IList<NotifyTemplate>>(File.ReadAllText(FileHelper.GetCurrPath(@"/DataSeed/dt_notify_template.json")));
            if (notifyList != null)
            {
                modelBuilder.Entity<NotifyTemplate>().HasData(notifyList);
            }
            IList<MemberGroup>? groupList = JsonHelper.ToJson<IList<MemberGroup>>(File.ReadAllText(FileHelper.GetCurrPath(@"/DataSeed/dt_member_group.json")));
            if (groupList != null)
            {
                modelBuilder.Entity<MemberGroup>().HasData(groupList);
            }
        }
    }
}
